import Module from "./module.js";
import { forEachValue } from "../utils.js";
export default class ModuleCollection {
  constructor(rootModule) {
    this.root = null;
    this.register(rootModule, []);
  }
  /**
   *
   * @param {*} module  模块对象
   * @param {*} path    模块路径数组 每次递归调用时，会将当前模块的路径添加到数组中
   */
  register(module, path) {
    // 注册模块
    const newModule = new Module(module);
    // 把新模块挂载到模块对象上
    // module.newModule = newModule;
    //  注册根模块
    if (path.length === 0) {
      this.root = newModule;
    } else {
      // 假设当前 path 为 ["aCount","cCount"]，模拟执行顺序：
      // 1. childPath = ["aCount"]（去掉最后一项）
      // 2. reduce 从 this.root 开始，先取 key="aCount" 的子模块，得到 aCount 模块
      // 3. 此时 childPath 遍历结束，parent 就是 aCount 模块
      // 4. 最后把 cCount 模块挂到 aCount 模块下
      let childPath = path.slice(0, -1);

      const parent = childPath.reduce((module, key) => {
        return module.getChild(key);
      }, this.root);

      parent.addChild(path[path.length - 1], newModule);
    }
    //  递归注册子模块
    if (module.modules) {
      forEachValue(module.modules, (childModule, key) => {
        this.register(childModule, path.concat(key));
      });
    }
    return newModule;
  }
  /**
   * 获取模块的命名空间
   * @param {*} path 模块路径数组
   * @returns 模块的命名空间字符串
   */
  getNamespace(path) {
    let module = this.root;
    // [a,c]
    return path.reduce((namespace, key) => {
      module = module.getChild(key); //子模块
      // 如果子模块开启了命名空间，就添加到命名空间中
      return namespace + (module.namespaced ? key + "/" : "");
    }, "");
  }
}
